#define VAR_BTN_GLOBALS
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_wifi.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_heap_caps.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "driver/rmt.h"
#include "esp_log.h"
#include "button.h"


#define TAG "btn"
#define DEFAULT_VREF    1100                            /*!< Use adc2_vref_to_gpio() to obtain a better estimate */
#define NO_OF_SAMPLES   64
#define SAMPLE_TIME     200                             /*!< Sampling time(ms) */
#define DEVIATION 0.1

static const adc_channel_t channel = ADC_CHANNEL_5;     /*!< PIO7 if ADC1, GPIO17 if ADC2 */
static const adc_bits_width_t width = ADC_WIDTH_BIT_13;

static const adc_atten_t atten = ADC_ATTEN_DB_11;
static const adc_unit_t unit = ADC_UNIT_1;

double adc_voltage_conversion(uint32_t adc_reading)
{
    double voltage = 0;

    voltage = (2.60 * adc_reading) / 8191;

    return voltage;
}

void button_task(void *arg)
{
    uint32_t adc_reading = 0;
    double voltage = 0;
    while (1)
    {
        /*!< Multisampling */
        for (int i = 0; i < NO_OF_SAMPLES; i++)
        {
            if (unit == ADC_UNIT_1)
            {
                adc_reading += adc1_get_raw((adc1_channel_t)channel);
            }
            else
            {
                int raw;
                adc2_get_raw((adc2_channel_t)channel, width, &raw);
                adc_reading += raw;
            }
        }

        adc_reading /= NO_OF_SAMPLES;

        voltage = adc_voltage_conversion(adc_reading);
        // printf("ADC%d CH%d Raw: %d   ; Voltage: %0.2lfV  ;  keyValue=%d\r\n", unit, channel, adc_reading, voltage,keyValue);
        if (voltage > 2.41 - DEVIATION  && voltage <= 2.41 + DEVIATION)
        {
            if (keyValue == 0)
            {
                keyValue = 1;
                xQueueSend(btnQueue, (unsigned char *)&keyValue, 0);
            }

        }
        else if (voltage > 1.98 - DEVIATION && voltage <= 1.98 + DEVIATION)
        {
            if (keyValue == 0)
            {
                keyValue = 2;
                xQueueSend(btnQueue, (unsigned char *)&keyValue, 0);
            }
        }
        else if (voltage > 1.65 - DEVIATION && voltage <= 1.65 + DEVIATION)
        {
            if (keyValue == 0)
            {
                keyValue = 3;
                xQueueSend(btnQueue, (unsigned char *)&keyValue, 0);
            }
        }
        else if (voltage > 1.11 - DEVIATION && voltage <= 1.11 + DEVIATION)
        {
            if (keyValue == 0)
            {
                keyValue = 4;
                xQueueSend(btnQueue, (unsigned char *)&keyValue, 0);
            }
        }
        else if (voltage > 0.91 - DEVIATION && voltage <= 0.91 + DEVIATION)
        {
            if (keyValue == 0)
            {
                keyValue = 5;
                xQueueSend(btnQueue, (unsigned char *)&keyValue, 0);
            }
        }
        else if (voltage > 0.82 - DEVIATION && voltage <= 0.82 + DEVIATION)
        {
            if (keyValue == 0)
            {
                keyValue = 5;
                xQueueSend(btnQueue, (unsigned char *)&keyValue, 0);
            }
        }
        else if (voltage > 0.38 - DEVIATION && voltage <= 0.38 + DEVIATION)
        {
            if (keyValue == 0)
            {
                keyValue = 6;
                xQueueSend(btnQueue, (unsigned char *)&keyValue, 0);
            }
        }
        else
        {
            keyValue = 0;
        }
        if(keyValue != 0)
        {
            ESP_LOGI(TAG, "Key Value: %d", keyValue);
        }
        vTaskDelay(200 / portTICK_PERIOD_MS);
    }
}
void adc_init(void)
{
    if (unit == ADC_UNIT_1)
    {
        adc1_config_width(width);
        adc1_config_channel_atten(channel, atten);
    }
    else
    {
        adc2_config_channel_atten((adc2_channel_t)channel, atten);
    }
}
QueueHandle_t button_init()
{
    btnQueue = xQueueCreate(1, sizeof(unsigned char));
    adc_init();
    xTaskCreate(button_task, "btn", 2048, NULL, 5, NULL);
    return btnQueue;
}

int wait_key_value(unsigned char *value, int delay)
{
    return xQueueReceive(btnQueue, value, delay);
}